package com.parking.stall.controller;


import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.parking.common.core.model.PageInfo;
import com.parking.common.core.model.Result;
import com.parking.common.core.model.StateData;
import com.parking.common.core.util.JwtUtil;
import com.parking.stall.dto.CertifiedStallDetailsDTO;
import com.parking.stall.dto.RentersSelectStallDTO;
import com.parking.stall.dto.StallRentDto;
import com.parking.stall.form.*;
import com.parking.stall.dto.StallDto;
import com.parking.stall.entity.StallInfo;
import com.parking.stall.exception.StallException;
import com.parking.stall.exceptionCode.StallExceptionCode;
import com.parking.stall.param.*;
import com.parking.stall.service.StallInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 彭于晏
 * @since 2023年11月29日
 */
@RestController
@RequestMapping("/stallInfo")
@Api(tags = "车位信息接口")
public class StallInfoController {

    /*车位信息*/

    @Autowired
    private StallInfoService stallInfoService;

    /**
     * 连接测试
     * test1
     */
    @GetMapping("/add")
    public Result test1(){
        return Result.getResult().setData("aaaa");
    }


    /**
     * platformSelect:平台查询车位信息（分页、带条件）
     * @param form：平台查询车位信息对象
     * @param authorization：token
     * @return PageInfo：分页对象
     * @throws Exception
     */
    @ApiOperation("平台查询车位信息")
    @PostMapping("/platformSelect.platform")
    public Result<PageInfo>  platformSelect(@RequestBody PlatformSelectStallInfoForm form ,@RequestHeader String authorization)throws Exception{
//        PlatformSelectStallInfoDTO
        JwtUtil.getPlatformId(authorization);
        PlatformSelectStallInfoParam param = BeanUtil.toBean(form, PlatformSelectStallInfoParam.class);
        PageInfo pageInfo=stallInfoService.platformSelect(param);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * addStall:物业新增车位（批量，带条件）
     * @param authorization：token
     * @param form:批量新增车位信息
     * @return true/false
     * @throws Exception
     */
    @PostMapping("/addStall.certified")
    @ApiOperation("物业新增车位（批量）")
    public Result<Boolean> addStall (@RequestBody AddStallInfoForm form ,@RequestHeader("authorization") String authorization) throws Exception{
        Integer certifiedAccountId = JwtUtil.getCertifiedAccountId(authorization);
        AddStallInfoParam param = BeanUtil.toBean(form,AddStallInfoParam.class);
        param.setCertifiedAccountId(certifiedAccountId);
        Boolean b = stallInfoService.addStall(param);
        return Result.getResult().setData(b).setMessage("新增成功");
    }


    /**
     * certifiedSelect:物业查询车位（分页、带条件）
     * @param authorization :token
     * @param form :物业查车位信息参数
     * @return PageInfo：分页对象
     * @throws Exception
     */
    @PostMapping("/certifiedSelect.certified")
    @ApiOperation("物业查询车位（分页、带条件）")
    public Result<PageInfo> certifiedSelect(@RequestBody CertifiedSelectStallInfoForm form,@RequestHeader String authorization ) throws Exception{
        Integer certifiedAccountId = JwtUtil.getCertifiedAccountId(authorization);
        CertifiedSelectStallInfoParam param = BeanUtil.toBean(form, CertifiedSelectStallInfoParam.class);
        param.setCertifiedAccountId(certifiedAccountId);
        PageInfo pageInfo=stallInfoService.certifiedSelect(param);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**
     * certifiedSetStallState:物业设置车位状态：上下架
     * @param authorization :token
     * @param form :物业设置车位上下架参数对象
     * @return Boolean
     * @throws Exception
     */
    @PostMapping("/certifiedSetStallState.certified")
    @ApiOperation("物业设置车位状态(车位上下架)")
    public Result<Boolean> certifiedSetStallState(@RequestBody CertifiedSetStallStateForm form,@RequestHeader String authorization)throws Exception{
        Integer certifiedAccountId = JwtUtil.getCertifiedAccountId(authorization);
        CertifiedSetStallStateParam param = BeanUtil.toBean(form, CertifiedSetStallStateParam.class);
        param.setCertifiedAccountId(certifiedAccountId);
        Boolean b = stallInfoService.certifiedSetStallState(param);
        return Result.getResult(Boolean.class).setMessage("设置成功").setData(b);
    }

    /**
     * certifiedStallDetails:车位详情（物业根据车位信息id查询车位详情）
     * @param authorization :token
     * @param stallInfoId :车位信息id
     * @return CertifiedStallDetailsDTO：车位信息dto参数对象
     * @throws Exception
     */
    @PostMapping("/certifiedStallDetails.certified/{stallInfoId}")
    @ApiOperation("车位详情（物业根据车位信息id查询车位详情）")
    public Result<CertifiedStallDetailsDTO>  certifiedStallDetails(@PathVariable("stallInfoId") Integer stallInfoId,@RequestHeader String authorization)throws Exception{
        Integer certifiedAccountId = JwtUtil.getCertifiedAccountId(authorization);
        CertifiedStallDetailsDTO dto = stallInfoService.certifiedStallDetails (stallInfoId,certifiedAccountId);
        return Result.getResult(CertifiedStallDetailsDTO.class).setData(dto).setMessage("查询成功");
    }

    /**
     * rentersSelect：出租客查询车位
     * @param form 出租客查询车位信息（分页）
     * @param authorization :token
     * @return RentersSelectStallDTO 出租客查询车位信息返回参数
     * @throws Exception
     */
    @PostMapping("/rentersSelect.renters")
    @ApiOperation("出租客查询车位")
    public Result<PageInfo>  rentersSelect(@RequestBody RentersSelectStallForm form,@RequestHeader String authorization)throws Exception{
        Integer rentersId = JwtUtil.getRentersId(authorization);
        RentersSelectStallParam param = BeanUtil.toBean(form,RentersSelectStallParam.class);
        param.setRentersId(rentersId);
        PageInfo pageInfo = stallInfoService.rentersSelect(param);
        return Result.getResult(PageInfo.class).setData(pageInfo).setMessage("查询成功");
    }


    /**
     * rentersSetUp:出租客设置车位上架（日期，时间批量）
     * @param authorization :token
     * @return Boolean
     * @throws Exception
     */
    @PostMapping("rentersSetDown.renters")
    @ApiOperation("出租客设置车位上架（日期，时间批量）")
    public Result<Boolean> rentersSetUp(@RequestBody RentersSetUpStallForm form,@RequestHeader String authorization)throws Exception{
        Integer rentersId = JwtUtil.getRentersId(authorization);
        RentersSetUpStallParam param = BeanUtil.toBean(form,RentersSetUpStallParam.class);
        param.setRentersId(rentersId);
        Boolean b=stallInfoService.rentersSetUp(param);
        return Result.getResult(Boolean.class).setData(b).setMessage("上架成功");
    }


    /**
     * rentersSetDown:出租客设置车位下架
     * @param stallInId :车位id
     * @param authorization :token
     * @return Boolean
     * @throws Exception
     */
    @PostMapping("/rentersSetDown.renters/{stallInId}")
    @ApiOperation("出租客设置车位下架")
    public Result<Boolean> rentersSetDown(@PathVariable("stallInId") Integer stallInId,@RequestHeader String authorization)throws Exception{
        JwtUtil.getRentersId(authorization);
        Boolean b=stallInfoService.rentersSetDown(stallInId);
        return Result.getResult(Boolean.class).setData(b).setMessage("下架成功");
    }


    /**
     * userSelect: 用户查询车位（分页，带条件）
//     * @param authorization ：token
     * @param form :用户查询车位信息对象
     * @return PageInfo:分页对象
     * @throws Exception
     */
    @PostMapping("/userSelect")
    @ApiOperation("用户查询车位")
    public Result<PageInfo> userSelect(@RequestBody UserSelectStallInfoForm form/*,@RequestHeader String authorization*/)throws Exception{
//        JwtUtil.getUserId(authorization);
        UserSelectStallInfoParam param = BeanUtil.toBean(form, UserSelectStallInfoParam.class);
        PageInfo pageInfo = stallInfoService.userSelect(param);
        return Result.getResult(PageInfo.class).setMessage("查询成功").setData(pageInfo);
    }

    /**---------------------调用接口方法----------------------**/


    /**
     * 平台禁用物业信息id而下架车位操作
     * platformSetStallDown：平台根据物业信息id下架车位（平台模块调用）
     * @param certifiedInfoId:物业信息id
     * @return true/false
     */
   @ApiOperation("平台根据物业信息id下架车位（平台模块调用）")
   @GetMapping("/platformSetStallDown")
   public  Result<Boolean> platformSetStallDown(@RequestParam("certifiedInfoId") Integer certifiedInfoId){
       if (certifiedInfoId==null) {
            throw new StallException(StallExceptionCode.CERTIFIED_INFO_ID_IS_NULL);//物业信息id不存在
       }
       boolean b = stallInfoService.update(new UpdateWrapper<StallInfo>()
               .eq("certified_info_id", certifiedInfoId)
               .set("stall_up_down_state", StateData.STALL_STATE_DOWN));
       return Result.getResult(Boolean.class).setMessage("下架成功").setData(b);
   }


    /**
     * 物业查询车位数量（带条件：类型,物业信息id）
     * certifiedSelectStallNum：物业查询车位数量车位(物业调用)
     * @param form:物业查询车位数量
     * @return count：车位数量
     * @throws Exception
     */
    @PostMapping("/certifiedSelectStallNum")
    @ApiOperation("物业查询车位数量车位(物业调用)")
    public Result<Integer>  certifiedSelectStallNum(@RequestBody CertifiedSelectStallNumForm form) throws Exception{
        if (form==null) {
            throw new StallException(StallExceptionCode.CALL_PARAM_IS_NULL);//调用参数不存在
        }
        long count = stallInfoService.count(new QueryWrapper<StallInfo>()
                .eq("certified_info_id",form.getCertifiedInfoId())
                .eq("stall_type",form.getStallType())
                .eq("stall_up_down_state", StateData.STALL_STATE_UP));
        int num = (int) count;
        return Result.getResult(Integer.class).setMessage("查询成功").setData(num);
    }


    /**
     * selectStallInfoById:用户根据车位信息id查询StallDto
     * 根据ID查询车位信息
     * 参数: 车位信息Id   stallInfoId
     * 返回: 车位区域     stallInfoArea
     *      车位编号     stallInfoNum
     *      车位类型     stallType 0普通 1充电
     *      物业信息Id   certifiedInfoId
     *      出租客信息Id rentersInfoId
     * 方法: 1.判断stallInfoId是否存在对应的车位信息 若不存在则抛异常 若下架也抛异常
     *      2.将车位信息放入Dto返回
     * */
    @GetMapping("/selectStallInfoById")
    @ApiOperation("根据ID查询车位相关信息(订单调用)")
    Result<StallDto> selectStallInfoById(@RequestParam("stallInfoId") Integer stallInfoId) {
        if (stallInfoId==null) {
            throw new StallException(StallExceptionCode.STALL_INFO_ID_NULL);//车位信息id不存在
        }
        StallInfo stallInfo = stallInfoService.getById(stallInfoId);
        if (stallInfo==null) {
            throw new StallException(StallExceptionCode.STALL_INFO_OBJECT_IS_NULL);//车位对象不存在
        }
        if (stallInfo.getStallUpDownState()!= StateData.STALL_STATE_UP) {
            throw new StallException(StallExceptionCode.STALL_ALREADY_IS_DOWN);//车位已下架
        }
        StallDto dto = BeanUtil.toBean(stallInfo, StallDto.class);
        return Result.getResult(StallDto.class).setMessage("查询成功").setData(dto);
    }

    /**
     * selectStallInfoById:用户根据车位信息id查询StallDto
     * 根据ID查询车位信息 无论是否下架
     * 参数: 车位信息Id   stallInfoId
     * 返回: 车位区域     stallInfoArea
     *      车位编号     stallInfoNum
     *      车位类型     stallType 0普通 1充电
     *      物业信息Id   certifiedInfoId
     *      出租客信息Id rentersInfoId
     * 方法: 1.判断stallInfoId是否存在对应的车位信息 若不存在则抛异常
     *      2.将车位信息放入Dto返回
     * */
    @GetMapping("/selectStallInfoById2")
    @ApiOperation("根据ID查询车位相关信息 无论是否下架")
    Result<StallDto> selectStallInfoById2(@RequestParam("stallInfoId") Integer stallInfoId) {
        if (stallInfoId==null) {
            throw new StallException(StallExceptionCode.STALL_INFO_ID_NULL);//车位信息id不存在
        }
        StallInfo stallInfo = stallInfoService.getById(stallInfoId);
        if (stallInfo==null) {
            throw new StallException(StallExceptionCode.STALL_INFO_OBJECT_IS_NULL);//车位对象不存在
        }
        StallDto dto = BeanUtil.toBean(stallInfo, StallDto.class);
        return Result.getResult(StallDto.class).setMessage("查询成功").setData(dto);
    }

    /**
     * selectStallRentById:用户根据车位信息id查询StallRentDto
     * 根据车位信息ID查询车位出租时间计划
     * 参数: 车位信息Id       stallInfoId
     * 返回: 是否有出租计划    isPlan 0有出租计划 1没有出租计划(默认全天候出租)
     *      出租计划开始日期   startDate
     *      出租计划结束日期   endDate
     *      每日计划时间组     planTimes
     *                      开始时间      startTime
     *                      结束时间      endTime
     *                      举例 8点-12点 14点-18点 22点-24点 被表示为 {[startTime:8,endTime:12],[startTime:14,endTime:18],[startTime:22,endTime:24]}
     * 返回参数的条件:
     *       1. startDate<endDate
     *       2. planTimes 非空集 每个元素中 startTime取值0-23 endTime取值1-24 startTime<endTime
     *       3. planTimes 各个元素间不能交叉 也不能连续
     * 方法: 1.判断stallInfoId是否存在对应的车位信息 若不存在则抛异常 若下架也抛异常
     *      2.将车位出租计划放入Dto中返回
     * */
    @GetMapping("/selectStallRentById")
    @ApiOperation("根据车位信息ID查询车位出租时间计划(订单调用)")
    Result<StallRentDto> selectStallRentById(@RequestParam("stallInfoId") Integer stallInfoId) {
        if (stallInfoId==null) {
            throw new StallException(StallExceptionCode.STALL_INFO_ID_NULL);//车位信息id不存在
        }
        StallRentDto dto = stallInfoService.selectStallRentById(stallInfoId);
        return Result.getResult(StallRentDto.class).setMessage("查询成功").setData(dto);
    }

    /**
     * 根据出租客信息ID查询车位信息
     * 参数: 出租客信息Id   rentersInfoId
     * 返回: 车位信息Id   stallInfoId
     *      车位区域     stallInfoArea
     *      车位编号     stallInfoNum
     *      车位类型     stallType 0普通 1充电
     *      物业信息Id   certifiedInfoId
     *      出租客信息Id rentersInfoId
     * 方法: 1.查询rentersInfoId对应的所有车位 不论是否下架
     *      2.将车位信息放入Dto返回
     * */
    @GetMapping("/selectStallInfoByRentersId")
    @ApiOperation("根据出租客信息Id查询车位信息")
    Result<List<StallDto>> selectStallInfoByRentersId(@RequestParam("rentersInfoId") Integer rentersInfoId) {
        if (rentersInfoId==null) {
            throw new StallException(StallExceptionCode.RENTERS_ID_IS_NULL);//出租客id不存在
        }
        List<StallInfo> stallInfoList = stallInfoService.list();
        List<StallDto> dtos = BeanUtil.copyToList(stallInfoList, StallDto.class);
        return Result.getListResult(StallDto.class).setMessage("查询成功").setData(dtos);
    }
}

